const crypto = require('crypto');
const axios = require('axios');
const xml2js = require('xml2js');
const config = require('../config/config');

class WechatPay {
  constructor() {
    this.appId = config.wechat.appId;
    this.mchId = config.wechat.mchId;
    this.apiKey = config.wechat.apiKey;
    this.notifyUrl = config.wechat.notifyUrl;
  }

  // 生成签名
  generateSign(params) {
    // 按参数名ASCII码从小到大排序
    const sortedKeys = Object.keys(params).sort();
    const stringA = sortedKeys
      .filter(key => params[key] && key !== 'sign')
      .map(key => `${key}=${params[key]}`)
      .join('&');
    
    const stringSignTemp = `${stringA}&key=${this.apiKey}`;
    return crypto.createHash('md5').update(stringSignTemp).digest('hex').toUpperCase();
  }

  // 生成随机字符串
  generateNonceStr() {
    return crypto.randomBytes(16).toString('hex');
  }

  // 对象转XML
  objectToXml(obj) {
    const builder = new xml2js.Builder({
      rootName: 'xml',
      headless: true,
      renderOpts: { pretty: false }
    });
    return builder.buildObject(obj);
  }

  // XML转对象
  async xmlToObject(xml) {
    const parser = new xml2js.Parser({ explicitArray: false });
    return await parser.parseStringPromise(xml);
  }

  // 统一下单
  async unifiedOrder(params) {
    const orderParams = {
      appid: this.appId,
      mch_id: this.mchId,
      nonce_str: this.generateNonceStr(),
      body: params.body,
      out_trade_no: params.outTradeNo,
      total_fee: params.totalFee,
      spbill_create_ip: params.ip || '127.0.0.1',
      notify_url: this.notifyUrl,
      trade_type: 'JSAPI',
      openid: params.openid
    };

    orderParams.sign = this.generateSign(orderParams);
    const xmlData = this.objectToXml(orderParams);

    try {
      const response = await axios.post(
        'https://api.mch.weixin.qq.com/pay/unifiedorder',
        xmlData,
        { headers: { 'Content-Type': 'text/xml' } }
      );

      const result = await this.xmlToObject(response.data);
      return result.xml;
    } catch (error) {
      console.error('统一下单失败:', error);
      throw error;
    }
  }

  // 生成小程序支付参数
  generatePayParams(prepayId) {
    const params = {
      appId: this.appId,
      timeStamp: Math.floor(Date.now() / 1000).toString(),
      nonceStr: this.generateNonceStr(),
      package: `prepay_id=${prepayId}`,
      signType: 'MD5'
    };

    params.paySign = this.generateSign(params);
    return params;
  }

  // 验证回调签名
  verifyNotifySign(data) {
    const sign = data.sign;
    delete data.sign;
    const calculatedSign = this.generateSign(data);
    return sign === calculatedSign;
  }

  // 查询订单
  async queryOrder(orderNo) {
    const params = {
      appid: this.appId,
      mch_id: this.mchId,
      out_trade_no: orderNo,
      nonce_str: this.generateNonceStr()
    };

    params.sign = this.generateSign(params);
    const xmlData = this.objectToXml(params);

    try {
      const response = await axios.post(
        'https://api.mch.weixin.qq.com/pay/orderquery',
        xmlData,
        { headers: { 'Content-Type': 'text/xml' } }
      );

      const result = await this.xmlToObject(response.data);
      return result.xml;
    } catch (error) {
      console.error('查询订单失败:', error);
      throw error;
    }
  }
}

module.exports = new WechatPay();


